import { DOWNLOAD_NOVEL, UPDATE_NOVEL, GET_NOVEL, NOVEL_LIST, ADD_NOVEL, REMOVE_NOVEL, EDIT_NOVEL, SEARCH_NOVEL, GET_NOVEL_CHAPTER, SEARCH_NOVEL_WITH_ID } from './channel'
import db from './db'
import { downloadBookMeta, getBookChapter, getNovelChapter } from './index'
import { existsSync } from 'fs'
import { downloadSearch, parseSearch } from '../modules/search'
import _ from 'lodash'

const { novels, sources } = db

type DownloadNovelParams = {
  sourceId: string,
  bookUrl: string,
  [key: string]: any
}
export default {
  [DOWNLOAD_NOVEL]: async (params: DownloadNovelParams) => {
    const { sourceId, ...restData } = params
    const source: any = await sources().findOne({ _id: params.sourceId })
    if (!source) {
      throw new Error('找不到书源')
    }
    let url = params.bookUrl
    if (!_.startsWith(url, 'http')) {
      url = source.bookSourceUrl + url
    }
    let result = await novels().findOne({ bookUrl: url })
    if (result) {
      return result
    }
    result = await downloadBookMeta(source, url)
    result = await novels().insert({ ...restData, ...result})
    return result
  },
  [UPDATE_NOVEL]: async (params: { id: string, chapters: boolean }) => {
    const { id, chapters } = params
    let result: any = await novels().findOne({ _id: id })
    if (result) {
      const source = await sources().findOne({ _id: result.sourceId })
      if (source) {
        result = await downloadBookMeta(source, result.bookUrl)
        if(chapters) {
          result = { chapters: result.chapters }
        }
        result = await novels().update({ _id: id }, { $set: result })
        return result
      }
    }
    throw new Error('找不到书源')
  },
  [GET_NOVEL]: async (data: any) => {
    const result: any = await novels().findOne(data)
    if(Array.isArray(result.chapters)) {
      for (const chapter of result.chapters) {
        if (existsSync(getBookChapter(result._id, chapter.chapterUrl))) {
          chapter.cached = true
        } else {
          chapter.cached = false
        }
      }
    }
    return result
  },
  [NOVEL_LIST]: async () => {
    const result = await novels().find({}, { _id: 1, name: 1, kind: 1, author: 1, coverUrl: 1 })
    return result
  },
  [ADD_NOVEL]: async (data: any) => {
    const result = await novels().insert(data)
    return result
  },
  [REMOVE_NOVEL]: async (data: any) => {
    const result = await novels().remove(data, {})
    return result
  },
  [EDIT_NOVEL]: async (params: any) => {
    const { _id, ...update } = params
    const result = await novels().update({ _id }, { $set: update })
    return result
  },
  [SEARCH_NOVEL]: async (source: any, key: string) => {
    try {
      const res = await downloadSearch(source, key)
      const result = parseSearch(source, res)
      if(result) {
        return result.filter(x => !!x.name && x.name.includes(key))
      }
      return []
    } catch (e) {
      if(e.code === "ECONNRESET") {
        await db.sources().update({ _id: source._id }, { $set: { enable: false } })
      }
      throw e
    }
  },
  [SEARCH_NOVEL_WITH_ID]: async (params: { sourceId: string, key: string }) => {
    const source = await db.sources().findOne({ _id: params.sourceId })
    if(!source) {
      throw new Error("未找到来源")
    }
    try {
      const res = await downloadSearch(source, params.key)
      const result = parseSearch(source, res)
      if(result) {
        return result.filter(x => !!x.name && x.name.includes(params.key))
      }
      return []
    } catch (e) {
      if(e.code === "ECONNRESET") {
        await db.sources().update({ _id: params.sourceId }, { $set: { enable: false } })
      }
      throw e
    }
  },
  [GET_NOVEL_CHAPTER]: async (arg: { novelId: string, chapterId: string, refresh: string }) => {
    const { novelId, chapterId, refresh } = arg
      const novel: any = await db.novels().findOne({ _id: novelId })
      let result = await getNovelChapter(novel, chapterId, refresh)
      const chapterIndex = novel.chapters.findIndex((x: any) => x.chapterUrl === chapterId)
      const chapters = novel.chapters
      return {
          chapterList: [
            { title: 'Prev', id: chapters[chapterIndex - 1] ? chapters[chapterIndex - 1].chapterUrl : null },
            { title: 'Index', id: novelId },
            { title: 'Next', id: chapters[chapterIndex + 1] ? chapters[chapterIndex + 1].chapterUrl : null }
          ],
          html: result
      }
  }
}
